// 单个缺陷记录
export interface Defect {
  x: number; // 缺陷 x 坐标，非负
  y: number; // 缺陷 y 坐标，非负
  type: string; // 缺陷类型，任意字符串
  area: number; // 缺陷面积，非负
  longSide: number; // 缺陷长边长，非负
  shortSide: number; // 缺陷短边长，非负
  score: number; // 置信度，范围 [0, 1]
}

// 缺陷详细信息
export interface DefectDetails {
  type: string; // 缺陷类型，任意字符串
  area: number; // 缺陷面积
  longSide: number; // 缺陷长边长
  shortSide: number; // 缺陷短边长
  score: number; // 置信度
}

// 统计信息接口
export interface Stats {
  count: number; // 总缺陷数
  totalArea: number; // 总面积
  maxLongSide: number; // 最长长边
  minLongSide: number; // 最短长边
  maxShortSide: number; // 最长短边
  minShortSide: number; // 最短短边
  maxArea: number; // 最大面积
  minArea: number; // 最小面积
  [key: string]: number; // 索引签名，允许动态字段
}

// 每种缺陷类型的分组（包含缺陷列表和统计）
export interface DefectGroup {
  details: DefectDetails[]; // 缺陷列表
  stats: Stats; // 该类型缺陷的统计
}

// 按坐标聚合的缺陷集合
export interface AggregatedDefect {
  x: number; // 缺陷 x 坐标
  y: number; // 缺陷 y 坐标
  flaws: Map<string, DefectGroup>; // 按类型分组，包含缺陷列表和统计
  stats?: Stats; // 总体统计
}

// 过滤规则接口（针对统计数据）
export interface FilterRule {
  field: string; // 字段路径，如 'flaws.scratch.stats.count'
  op: ">" | "<" | ">=" | "<=" | "==" | "!="; // 操作符
  value: number; // 比较值
}

// 类型存在规则接口
export interface TypeRule {
  type: string; // 缺陷类型，如 'scratch'
  op: "exists" | "not_exists"; // 是否存在该类型
}

// 逻辑规则接口
type LogicalOperator = "AND" | "OR" | "NOT";
export interface LogicalRule {
  op: LogicalOperator; // 逻辑运算符
  rules: (FilterRule | TypeRule | LogicalRule)[]; // 子规则（支持嵌套）
}

// 处理后的数据类
export class ProcessedData {
  private data: AggregatedDefect[];

  constructor(data: AggregatedDefect[]) {
    this.data = data;
  }

  // 打印方法：将 Map 转为对象并输出格式化 JSON
  print(): void {
    const printableData = this.data.map((item) => ({
      x: item.x,
      y: item.y,
      flaws: Object.fromEntries(
        Array.from(item.flaws.entries()).map(([type, group]) => [
          type,
          { details: group.details, stats: group.stats },
        ])
      ),
      stats: item.stats,
    }));
    console.log(JSON.stringify(printableData, null, 2));
  }

  // 获取数据（可选，用于访问原始数据）
  getData(): AggregatedDefect[] {
    return this.data;
  }

  // 验证 FilterRule 格式
  private validateFilterRule(rule: FilterRule): void {
    if (!rule.field.match(/^flaws\.[^.]+\.stats\.[^.]+$/)) {
      throw new Error(
        `Invalid field format: ${rule.field}. Expected 'flaws.<type>.stats.<field>'`
      );
    }
    if (![">", "<", ">=", "<=", "==", "!="].includes(rule.op)) {
      throw new Error(`Unsupported operator: ${rule.op}`);
    }
  }

  // 验证 TypeRule 格式
  private validateTypeRule(rule: TypeRule): void {
    if (typeof rule.type !== "string" || rule.type.trim() === "") {
      throw new Error(`Invalid type: ${rule.type}`);
    }
    if (!["exists", "not_exists"].includes(rule.op)) {
      throw new Error(`Unsupported type operator: ${rule.op}`);
    }
  }

  // 评估 FilterRule
  private evaluateFilterRule(
    item: AggregatedDefect,
    rule: FilterRule
  ): boolean {
    const match = rule.field.match(/^flaws\.([^.]+)\.stats\.(.+)$/);
    if (!match) return false; // 已在上方验证
    const type = match[1];
    const statField = match[2];
    const value = item.flaws.get(type)?.stats[statField] || 0;

    switch (rule.op) {
      case ">":
        return value > rule.value;
      case "<":
        return value < rule.value;
      case ">=":
        return value >= rule.value;
      case "<=":
        return value <= rule.value;
      case "==":
        return value === rule.value;
      case "!=":
        return value !== rule.value;
      default:
        return false; // 已在上方验证
    }
  }

  // 评估 TypeRule
  private evaluateTypeRule(item: AggregatedDefect, rule: TypeRule): boolean {
    const hasType = item.flaws.has(rule.type);
    return rule.op === "exists" ? hasType : !hasType;
  }

  // 递归评估规则（FilterRule, TypeRule 或 LogicalRule）
  private evaluateRule(
    item: AggregatedDefect,
    rule: FilterRule | TypeRule | LogicalRule
  ): boolean {
    if ("field" in rule) {
      // FilterRule
      this.validateFilterRule(rule);
      return this.evaluateFilterRule(item, rule);
    } else if ("type" in rule) {
      // TypeRule
      this.validateTypeRule(rule);
      return this.evaluateTypeRule(item, rule);
    } else {
      // LogicalRule
      if (!["AND", "OR", "NOT"].includes(rule.op)) {
        throw new Error(`Unsupported logical operator: ${rule.op}`);
      }
      if (rule.op === "NOT" && rule.rules.length !== 1) {
        throw new Error("NOT operator requires exactly one rule");
      }
      if (rule.op !== "NOT" && rule.rules.length === 0) {
        throw new Error(`${rule.op} operator requires at least one rule`);
      }

      if (rule.op === "AND") {
        return rule.rules.every((subRule) => this.evaluateRule(item, subRule));
      } else if (rule.op === "OR") {
        return rule.rules.some((subRule) => this.evaluateRule(item, subRule));
      } else {
        // NOT
        return !this.evaluateRule(item, rule.rules[0]);
      }
    }
  }

  // 过滤方法：基于每种缺陷类型的统计数据和类型存在性，支持逻辑运算符
  filterByTypeStats(rule: LogicalRule): ProcessedData {
    // 验证最外层规则
    if (!["AND", "OR", "NOT"].includes(rule.op)) {
      throw new Error(`Unsupported logical operator: ${rule.op}`);
    }
    if (rule.op === "NOT" && rule.rules.length !== 1) {
      throw new Error("NOT operator requires exactly one rule");
    }
    if (rule.op !== "NOT" && rule.rules.length === 0) {
      throw new Error(`${rule.op} operator requires at least one rule`);
    }

    const filteredData = this.data.filter((item) =>
      this.evaluateRule(item, rule)
    );
    return new ProcessedData(filteredData);
  }
}
